package com.wngbms.netty.seatdemo.server;

import com.wngbms.netty.seatdemo.message.BaseHeader;
import com.wngbms.netty.seatdemo.message.SeatInMessage;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import lombok.extern.slf4j.Slf4j;

import java.net.SocketAddress;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
public class SeatDecoderHandler extends ByteToMessageDecoder {

    public static final Map<SocketAddress, SeatInMessage> RECEIVE_MAP = new ConcurrentHashMap<>();

    @Override
    protected void decode(ChannelHandlerContext ctx, ByteBuf byteBuf, List<Object> out) throws Exception {
        SocketAddress remoteAddress = ctx.channel().remoteAddress();

        int readableBytes;

        do {
            SeatInMessage seatInMessage = RECEIVE_MAP.computeIfAbsent(remoteAddress, socketAddress -> new SeatInMessage());
            seatInMessage.setChannelHandlerContext(ctx);

            BaseHeader baseHeader = seatInMessage.getBaseHeader();
            if (baseHeader == null) {
                baseHeader = new BaseHeader();
            }

            if (!baseHeader.isFinish()) {
                baseHeader.writeHeader(byteBuf);
                seatInMessage.setBaseHeader(baseHeader);
            } else {
                readableBytes = byteBuf.readableBytes();
                if (readableBytes > 0) {
                    seatInMessage.writeBody(byteBuf, readableBytes);
                }
            }

            if (seatInMessage.finished()) {
                RECEIVE_MAP.remove(remoteAddress);
                out.add(seatInMessage);
            }

        } while (byteBuf.readableBytes() > 0);

        /*int readableBytes = byteBuf.readableBytes();
        SeatInMessage seatInMessage = RECEIVE_MAP.computeIfAbsent(remoteAddress, socketAddress -> new SeatInMessage());

        BaseHeader baseHeader = seatInMessage.getBaseHeader();
        if (baseHeader == null) {
            if (readableBytes < BaseHeader.HEADER_LENGTH) {
                log.info("可读字节数:{}小于指定请求头大小", readableBytes);
                return;
            } else {
                baseHeader = new BaseHeader();
                baseHeader.writeHeader(byteBuf);

                seatInMessage.setBaseHeader(baseHeader);
            }
        }

        readableBytes = byteBuf.readableBytes();
        if (readableBytes > 0) {
            seatInMessage.writeBody(byteBuf, readableBytes);
        }

        if (seatInMessage.finished()) {
            RECEIVE_MAP.remove(remoteAddress);
            out.add(seatInMessage);
        }*/
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        log.info("连接关闭...");
        SocketAddress socketAddress = ctx.channel().remoteAddress();
        RECEIVE_MAP.remove(socketAddress);
        log.info("删除用户信息");
        String userId = SeatBizHandler.USER_SOCKET_MAP.remove(socketAddress);
        log.info("删除用户用户通道");
        if (userId != null) {
            SeatBizHandler.USER_CHANNEL_MAP.remove(userId);
        }
        super.channelInactive(ctx);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        log.error("channel exp:{}", cause);
        Channel channel = ctx.channel();
        SocketAddress remoteAddress = channel.remoteAddress();
        RECEIVE_MAP.remove(remoteAddress);

        log.info("删除用户信息");
        String userId = SeatBizHandler.USER_SOCKET_MAP.remove(remoteAddress);
        if (userId != null) {
            log.info("删除用户用户通道");
            SeatBizHandler.USER_CHANNEL_MAP.remove(userId);
        }
    }
}
